! fpm run --example bench_array_constructor
program main

    use queue_m, only: queue_t
    type(queue_t) queue
    integer, allocatable :: array(:), queue_array(:)
    class(*), allocatable :: data
    real t1, t2

    ! Queue time complexity: O(1)
    call cpu_time(t1)
    do i = 1, 10000
        call queue%enqueue(i)
    end do
    call cpu_time(t2)

    write (*, *) "Time to enqueue 1000 elements: ", t2 - t1
    write (*, *) "Size of queue: ", queue%size()

    call cpu_time(t1)
    allocate(queue_array(queue%size()))
    do i = 1, 10000
        call queue%dequeue(data)
        queue_array(i) = to_int(data)
    end do
    call cpu_time(t2)
    
    write (*, *) "Time to dequeue 1000 elements: ", t2 - t1
    write (*, *) "Size of queue (now empty): ", queue%size()
    write (*, *) "Size of Queue array: ", size(queue_array)

    ! Array append time complexity: O(n)
    ! Even if a special algorithm is used to expand the matrix in stages, the complexity will be still formed.
    call cpu_time(t1)
    allocate (array(0))
    do i = 1, 10000
        array = [array, i]
    end do
    call cpu_time(t2)

    write (*, *) "Time to allocate 1000 elements: ", t2 - t1
    write (*, *) "Size of array: ", size(array)

contains

    pure function to_int(in) result(out)
        class(*), intent(in) :: in
        integer :: out
        select type (in)
        type is (integer)
            out = in
        class default
            out = 0
        end select
    end function to_int

end program main

! Time to enqueue 1000 elements:    0.00000000
! Size of queue:        10000
! Time to dequeue 1000 elements:    0.00000000
! Size of queue (now empty):            0
! Size of Queue array:        10000
! Time to allocate 1000 elements:   0.109375000
! Size of array:        10000